/*
 * Copyright (c) 2014.
 * Private license for beyondts.
 * Contact beyondts for using, beyondts999@163.com
 */
package net.beyondts.mplug.utils;

import org.apache.commons.lang3.ArrayUtils;

import java.awt.*;
import java.io.File;
import java.math.BigInteger;

/**
 * Project: beyondts-basic<br/>
 * Description: <br/>
 * Created at: 2014年8月16日<br/>
 * Owned by beyondts.
 *
 * @author blazecrystal
 * @version 1.0.0
 */
public final class Transformer {
    /**
     * 字节单元大小，包含的字节数。
     */
    private static final int UNIT = 8;

    /**
     * 字节掩码。
     */
    private static final int MASK = 0x000000FF;

    /**
     * 短整型字节长度。
     */
    private static final int PER_LENGTH_SHORT = 2;

    /**
     * 整型字节长度。
     */
    private static final int PER_LENGTH_INT = 4;

    /**
     * 长整型字节长度。
     */
    private static final int PER_LENGTH_LONG = 8;

//    /**
//     * 十六进制显示字符。
//     */
//    private static final char[] CHARS_HEX = new char[]{'0', '1', '2', '3',
//            '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
//
//    private static final char[] CHARS_DUO = new char[]{'0', '1', '2', '3',
//            '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
//            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
//            'U', 'V'};

//    /**
//     * 十六进制掩码。
//     */
//    private static final int MAX_HEX = 0xF;
//
//    /**
//     * 十六进制对应字节个数。
//     */
//    private static final int LENGTH_HEX_BYTE = 2;
//
//    /**
//     * 进制（16）。
//     */
//    private static final int HEX = 16;
//
//    /**
//     * 2字节最大值。
//     */
//    private static final int MAX_BYTE = 256;

    /**
     * 把short转为指定长度的byte[]（最少2位）.
     * 超过2的数组，前几位应该是0，只有最后2位表示short
     *
     * @param src    short 待转的short
     * @param length int 转后的byte[]长度
     * @return byte[] 转换后的byte[]（最少2位）
     */
    public static byte[] short2bytes(short src, int length) {
        byte[] tmp = new byte[length - PER_LENGTH_SHORT];
        return ArrayUtils.addAll(tmp, short2bytes(src));
    }

    /**
     * 把short转为byte[]（长度为2）.
     *
     * @param src short 待转的short
     * @return byte[] 转换后的byte[]（长度2）
     */
    public static byte[] short2bytes(short src) {
        byte[] dst = new byte[PER_LENGTH_SHORT];
        for (int i = 0; i < dst.length; i++) {
            dst[i] = (byte) ((src >> ((dst.length - 1 - i) * UNIT)) & MASK);
        }
        return dst;
    }

    /**
     * 把byte[]转为short.
     * 超过2的数组，前几位应该是0，只有最后2位表示short
     *
     * @param src byte[] 任意长度字节数组
     * @return short 转换后的short
     */
    public static short bytes2short(byte[] src) {
        short dst = 0;
        int tmp = 0;
        for (int i = 0; i < src.length; i++) {
            dst <<= UNIT;
            tmp = src[i] & MASK;
            dst |= tmp;
        }
        return dst;
    }

    /**
     * 把int转为指定长度的byte[]（最少4位）.
     * 超过4的数组，前几位应该是0，只有最后4位表示int
     *
     * @param src    int 待转的int
     * @param length int 转后的byte[]长度
     * @return byte[] 转换后的byte[]（最少4位）
     */
    public static byte[] int2bytes(int src, int length) {
        if (length > PER_LENGTH_INT) {
            byte[] tmp = new byte[length - PER_LENGTH_INT];
            return ArrayUtils.addAll(tmp, int2bytes(src));
        } else {
            return ArrayUtils.subarray(int2bytes(src), PER_LENGTH_INT - length,
                    PER_LENGTH_INT);
        }
    }

    /**
     * 把int转为byte[]（长度为4）.
     *
     * @param src int 待转的int
     * @return byte[] 转换后的byte[]（长度4）
     */
    public static byte[] int2bytes(int src) {
        byte[] dst = new byte[PER_LENGTH_INT];
        for (int i = 0; i < dst.length; i++) {
            dst[i] = (byte) ((src >> ((dst.length - 1 - i) * UNIT)) & MASK);
        }
        return dst;
    }

    /**
     * 把byte[]转为int.
     * 超过4的数组，前几位应该是0，只有最后4位表示int
     *
     * @param src byte[] 任意长度字节数组
     * @return int 转换后的int
     */
    public static int bytes2Int(byte[] src) {
        int dst = 0;
        int tmp = 0;
        for (int i = 0; i < src.length; i++) {
            dst <<= UNIT;
            tmp = src[i] & MASK;
            dst |= tmp;
        }
        return dst;
    }

    /**
     * 把long转为指定长度的byte[]（最少8位）.
     * 超过8的数组，前几位应该是0，只有最后8位表示long
     *
     * @param src    long 待转的long
     * @param length int 转后的byte[]长度
     * @return byte[] 转换后的byte[]（最少8位）
     */
    public static byte[] long2Bytes(long src, int length) {
        byte[] tmp = new byte[length - PER_LENGTH_LONG];
        return ArrayUtils.addAll(tmp, long2Bytes(src));
    }

    /**
     * 把long转为byte[]（长度为8）.
     *
     * @param src long 待转的long
     * @return byte[] 转换后的byte[]（长度8）
     */
    public static byte[] long2Bytes(long src) {
        byte[] dst = new byte[PER_LENGTH_LONG];
        for (int i = 0; i < dst.length; i++) {
            dst[i] = (byte) ((src >> ((dst.length - 1 - i) * UNIT)) & MASK);
        }
        return dst;
    }

    /**
     * 把byte[]转为long.
     * 超过8的数组，前几位应该是0，只有最后8位表示long
     *
     * @param src byte[] 任意长度字节数组
     * @return long 转换后的long
     */
    public static long bytes2long(byte[] src) {
        long dst = 0;
        int tmp = 0;
        for (int i = 0; i < src.length; i++) {
            dst <<= UNIT;
            tmp = src[i] & MASK;
            dst |= tmp;
        }
        return dst;
    }

    public static byte[] bigInteger2bytes(BigInteger bi) {
        byte tmp[] = null;
        if (bi == null) {
            return null;
        }

        if (bi.toByteArray().length == 33) {
            tmp = new byte[32];
            System.arraycopy(bi.toByteArray(), 1, tmp, 0, 32);
        } else if (bi.toByteArray().length == 32) {
            tmp = bi.toByteArray();
        } else {
            tmp = new byte[32];
            for (int i = 0; i < 32 - bi.toByteArray().length; i++) {
                tmp[i] = 0;
            }
            System.arraycopy(bi.toByteArray(), 0, tmp, 32 - bi.toByteArray().length, bi.toByteArray().length);
        }
        return tmp;
    }

    /**
     * 将文件路径转为本地表示.
     *
     * @param path {@link String} 待转换的路径
     * @return {@link String} 本地表示
     */
    public static String toLocalFilePath(String path) {
        return path.replace("/", File.separator).replace("\\", File.separator);
    }

    /**
     * 将文件路径转为本地显示，并以文件分隔符结束.
     *
     * @param path {@link String} 待转换的路径
     * @return {@link String} 本地显示的文件路径，以文件分隔符结束
     */
    public static String toLocalFilePathWithSeperatorEnd(String path) {
        String tmp = toLocalFilePath(path);
        if (tmp.lastIndexOf(File.separator) < tmp.length() - 1) {
            return tmp + File.separator;
        } else {
            return tmp;
        }
    }

    /**
     * 按分隔符组合byte数组。
     *
     * @param byteArray byte[] 字节数组
     * @param seperator {@link String} 分隔符
     * @return {@link String} 组合后的字符串
     */
    public static String join(byte[] byteArray, String seperator) {
        StringBuffer tmp = new StringBuffer();
        for (byte b : byteArray) {
            tmp.append(b);
            tmp.append(seperator);
        }
        return tmp.substring(0, tmp.length() - 1);
    }

    /**
     * 将十六进制格式的颜色信息转为java.awt.Color对象。
     *
     * @param hexColor {@link String} 十六进制格式的颜色值，必须6位，如000000
     * @return {@link Color} 颜色对象
     */
    public static Color hexColorString2Color(String hexColor) {
        final String hex = "0123456789ABCDEF";
        hexColor = hexColor.toUpperCase();
        int[] rgb = new int[3];
        for (int i = 0; i < rgb.length; i++) {
            rgb[i] = hex.indexOf(hexColor.charAt(2 * i)) * 16
                    + hex.indexOf(hexColor.charAt(2 * i + 1));
        }
        return new Color(rgb[0], rgb[1], rgb[2]);
    }

    /**
     * 将IPv4字符串转成数字。
     *
     * @param ipv4 String IPv4字符串，格式：xxx.xxx.xxx.xxx
     * @return int 转换后的数字
     */
    public static int ipv4ToInt(String ipv4) {
        String[] parts = ipv4.split("\\.");
        final int COUNT = 4;
        return Integer.parseInt(parts[0]) * 256 * 256 * 256 + Integer.parseInt(parts[1]) * 256 * 256 + Integer.parseInt(parts[2]) * 256 + Integer.parseInt(parts[3]);
    }

    /**
     * 构造函数.
     */
    private Transformer() {

    }
}
